#include "SLLString.h"

SLLString::SLLString() : m_pHead(nullptr), m_pTail(nullptr)
{
}

SLLString::SLLString(const std::string &other)
{
    m_pHead = new Node(other[0]);
    m_pTail = m_pHead;

    for (int i = 1; i < other.length(); i++)
    {
        m_pTail->next = new Node(other[i]);
        m_pTail = m_pTail->next;
    }
}

SLLString::SLLString(const SLLString &other)
{
    m_pHead = new Node(other.m_pHead->data);
    m_pTail = m_pHead;

    Node *pTemp = other.m_pHead->next;

    while (pTemp != nullptr)
    {
        m_pTail->next = new Node(pTemp->data);
        m_pTail = m_pTail->next;
        pTemp = pTemp->next;
    }
}

SLLString::~SLLString()
{
    Node *pTemp = m_pHead;

    while (pTemp != nullptr)
    {
        Node *pDelete = pTemp;
        pTemp = pTemp->next;
        delete pDelete;
    }

    m_pHead = nullptr;
    m_pTail = nullptr;
}

SLLString &SLLString::operator=(const SLLString &other)
{
    if (this != &other)
    {
        Node *pTemp = m_pHead;

        // Delete the current list
        while (pTemp != nullptr)
        {
            Node *pDelete = pTemp;
            pTemp = pTemp->next;
            delete pDelete;
        }

        m_pHead = new Node(other.m_pHead->data);
        m_pTail = m_pHead;

        pTemp = other.m_pHead->next;

        while (pTemp != nullptr)
        {
            m_pTail->next = new Node(pTemp->data);
            m_pTail = m_pTail->next;
            pTemp = pTemp->next;
        }
    }

    return *this;
}

SLLString &SLLString::operator+=(const SLLString &other)
{
    Node *pTemp = other.m_pHead;

    while (pTemp != nullptr)
    {
        m_pTail->next = new Node(pTemp->data);
        m_pTail = m_pTail->next;
        pTemp = pTemp->next;
    }

    return *this;
}

std::ostream &operator<<(std::ostream &os, const SLLString &other)
{
    Node *pTemp = other.m_pHead;

    while (pTemp != nullptr)
    {
        os << pTemp->data;
        pTemp = pTemp->next;
    }

    return os;
}

char &SLLString::operator[](const int n)
{
    Node *pTemp = m_pHead;

    for (int i = 0; i < n; i++)
    {
        pTemp = pTemp->next;
    }

    return pTemp->data;
}

int SLLString::length()
{
    int len = 0;
    Node *pTemp = m_pHead;

    while (pTemp != nullptr)
    {
        len++;
        pTemp = pTemp->next;
    }

    return len;
}

int SLLString::findSubstring(const std::string substring)
{
    int thisLen = length();
    int len = substring.length();
    Node *pTemp = m_pHead;

    for (int i = 0; i < thisLen; i++)
    {
        if (pTemp->data == substring[0])
        {
            Node *pTemp2 = pTemp;
            int j = 0;

            while (pTemp2 != nullptr && j < len)
            {
                if (pTemp2->data != substring[j])
                {
                    break;
                }

                pTemp2 = pTemp2->next;
                j++;
            }

            if (j == len)
            {
                return i;
            }
        }

        pTemp = pTemp->next;
    }

    return -1;
}

void SLLString::erase(char c)
{
    Node *pTemp = m_pHead;

    while (pTemp != nullptr)
    {
        if (pTemp->data == c)
        {
            Node *pDelete = pTemp;
            pTemp = pTemp->next;
            delete pDelete;
        }
        else
        {
            break;
        }
    }

    m_pHead = pTemp;

    while (pTemp != nullptr && pTemp->next != nullptr)
    {
        if (pTemp->next->data == c)
        {
            Node *pDelete = pTemp->next;
            pTemp->next = pTemp->next->next;
            delete pDelete;
        }
        else
        {
            pTemp = pTemp->next;
        }
    }

    m_pTail = pTemp;
}
